package pe.com.casadesign.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.stereotype.Repository;

import pe.com.casadesign.dao.TiendaDAO;
import pe.com.casadesign.domain.ListaTienda;
import pe.com.casadesign.domain.Tienda;

/**
 * Implementacion de TiendaDAO.
 * 
 * @author Pedro Vera
 * 
 */
@Repository
public class TiendaDAOImpl implements TiendaDAO {
	private static final Logger logger = LoggerFactory.getLogger(TiendaDAOImpl.class);
	
	// Nombre Procedimientos Almacenados
	private static String SP_LISTAR_TIENDA = "SP_LISTAR_TIENDA";
	private static String SP_OBTENER_TIENDA = "SP_OBTENER_TIENDA";
	private static String SP_REGISTRAR_TIENDA = "SP_REGISTRAR_TIENDA";
	private static String SP_MODIFICAR_TIENDA = "SP_MODIFICAR_TIENDA";
	private static String SP_ELIMINAR_TIENDA = "SP_ELIMINAR_TIENDA";

	// Parametros de Entrada
	private static String PARAM_CODTIENDA = "p_codtienda";
	private static String PARAM_NOMBRE = "p_nombre";
	private static String PARAM_DESCRIPCION = "p_descripcion";
	private static String PARAM_DIRECCION = "p_direccion";
	private static String PARAM_DISTRITO = "p_distrito";
	private static String PARAM_ESTADO = "p_estado";
	
	// Parametros de Salida
	private static String CODTIENDA = "CODTIENDA";
	private static String NOMBRE = "NOMBRE";
	private static String DESCRIPCION = "DESCRIPCION";
	private static String DIRECCION = "DIRECCION";
	private static String DISTRITO = "DISTRITO";
	private static String ESTADO = "ESTADO";
	private static String FECHAREGISTRO = "FECHAREGISTRO";
	
	private static String LISTADO = "LISTADO";
	
	private static String TOTAL_FILAS_AFECTADAS = "#update-count-1";
	
	private JdbcTemplate jdbcTemplate;

	@Autowired
    public void setDataSource(DataSource dataSource)
    {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
	
	@Override
	public ListaTienda listarTienda(Tienda tienda) {
		logger.info("listarTienda");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LISTAR_TIENDA).
	    						  returningResultSet(LISTADO, new RowMapper<Tienda>(){
									@Override
									public Tienda mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        tienda.setNombre(rs.getString(NOMBRE));
								        tienda.setDescripcion(rs.getString(DESCRIPCION));
								        tienda.setDireccion(rs.getString(DIRECCION));
								        tienda.setDistrito(rs.getString(DISTRITO));
								        tienda.setEstado(rs.getString(ESTADO));
								        tienda.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return tienda;
								    }
	    						  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_NOMBRE, tienda.getNombre())
	    								.addValue(PARAM_ESTADO, tienda.getEstado()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Tienda> listaTienda= (List<Tienda>)data.get(LISTADO);
        
		// Instanciando objeto ListaTienda
		ListaTienda listaTiendaResultado = new ListaTienda();
        // Estableciendo resultado al objeto listaTiendaResultado
		listaTiendaResultado.setLista(listaTienda);
        
        if (logger.isDebugEnabled() && listaTiendaResultado != null)
        {
            logger.debug("size=" + listaTiendaResultado.size());
        }
        return listaTiendaResultado;
	}

	@Override
	public Tienda obtenerTienda(Tienda tienda) {
		logger.info("obtenerTienda");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_OBTENER_TIENDA).
								  returningResultSet(LISTADO, new RowMapper<Tienda>(){
									@Override
									public Tienda mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        tienda.setNombre(rs.getString(NOMBRE));
								        tienda.setDescripcion(rs.getString(DESCRIPCION));
								        tienda.setDireccion(rs.getString(DIRECCION));
								        tienda.setDistrito(rs.getString(DISTRITO));
								        tienda.setEstado(rs.getString(ESTADO));
								        tienda.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return tienda;
								    }
								  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODTIENDA, tienda.getCodigo());

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Tienda> listaTienda= (List<Tienda>)data.get(LISTADO);
        
		// Declarando objeto tienda Obtenido
		Tienda tiendaObtenido = null;
		
		if (listaTienda != null && listaTienda.size()>0){
			// Obteniendo el primer elemento de la lista de tienda
			tiendaObtenido = listaTienda.get(0);
		}
        
        if (logger.isDebugEnabled() && listaTienda != null)
        {
            logger.debug("size=" + listaTienda.size());
        }
        
		return tiendaObtenido;
	}

	@Override
	public boolean registrarTienda(Tienda tienda) {
		logger.info("registrarTienda");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_REGISTRAR_TIENDA);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_NOMBRE, tienda.getNombre())
	    								.addValue(PARAM_DESCRIPCION, tienda.getDescripcion())
	    								.addValue(PARAM_DIRECCION , tienda.getDireccion())
	    								.addValue(PARAM_DISTRITO, tienda.getDistrito())
	    								.addValue(PARAM_ESTADO, tienda.getEstado())
	    								.addValue(PARAM_CODTIENDA, tienda.getCodigo());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    return totalRegistrosAfectado > 0;
	}

	@Override
	public boolean modificarTienda(Tienda tienda) {
		logger.info("modificarTienda");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_MODIFICAR_TIENDA);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODTIENDA, tienda.getCodigo())
	    								.addValue(PARAM_NOMBRE, tienda.getNombre())
	    								.addValue(PARAM_DESCRIPCION, tienda.getDescripcion())
	    								.addValue(PARAM_DIRECCION , tienda.getDireccion())
	    								.addValue(PARAM_DISTRITO, tienda.getDistrito())
	    								.addValue(PARAM_ESTADO, tienda.getEstado());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    return totalRegistrosAfectado > 0;
	}

	@Override
	public boolean eliminarTienda(Tienda tienda) {
		logger.info("eliminarTienda");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_ELIMINAR_TIENDA);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODTIENDA, tienda.getCodigo());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    return totalRegistrosAfectado > 0;
	}

}
